package com.linkdood.app.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.linkdood.app.annotation.PartialUpdateArgumentResolver;
import com.linkdood.app.constants.ErrorCode;
import com.linkdood.app.exception.GeneralException;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.format.FormatterRegistry;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

/**
 * web mvc 的配置
 *
 * @author YunJ
 */
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Value("${customize.upload.path}")
    private String uploadPath;

    private final ApplicationContext applicationContext;

    private final PartialUpdateArgumentResolver partialUpdateArgumentResolver;

    public MyWebMvcConfigurer(ApplicationContext applicationContext, PartialUpdateArgumentResolver partialUpdateArgumentResolver) {
        this.applicationContext = applicationContext;
        this.partialUpdateArgumentResolver = partialUpdateArgumentResolver;
    }

    /**
     * Adds the patch argument resolver
     * 自定义实现 @Patch 时，需要解析参数
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(partialUpdateArgumentResolver);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        File fileDir = new File(uploadPath);
        try {
            FileUtils.forceMkdir(fileDir);
        } catch (IOException e) {
            throw new GeneralException(ErrorCode.ERROR_CONFIGURATION_FILE);
        }
        String path = fileDir.getAbsolutePath();
        registry.addResourceHandler("/api/static-files/**").addResourceLocations("file:" + path);
    }

    /**
     * TODO 正式发布的时候持续集成需要去掉此处
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 加入此处配置和 WebSecurityCorsFilter 配合使用，否则当 POST 请求发出的时候，会先发 OPTIONS 这时候会提示 403
        // 下面一行代码持续集成会修改, 勿动
        registry.addMapping("/**").allowCredentials(true).allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
    }

    /**
     * 添加类型转换器，转换 LocalDateTime 为 ISO-8601 "2020-10-10T10:10:10.000Z" 格式
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new LocalDateTimeConvert());
    }

    /**
     * 配置 Jackson 添加 LocalDateTime 解析器 解析为 "2020-10-10T10:10:10.000Z" 格式
     */
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

}
